#lang scheme

(define % remainder)

(define (in a b) (if (empty? b) #f (if (equal? a (car b)) #t (in a (cdr b)))))
  

(define (z1 lst)
  (define (iter head tail c)
    (if (empty? head)                                            ; база - возвращаем кол-во "уникальных" элементов
        c
        (if (in (car head) tail)                                 ; встречается ли элемент более одного раза в списке?
            (iter (cdr head) (cons (car head) tail) c)           ; встретился - пропуск
            (iter (cdr head) (cons (car head) tail) (+ c 1)))))  ; больше не встречается - увеличиваем счётчик
  (iter lst null 0))

;------------------------------------------------------------------

; ( myAppend '(1 2) '(3 4)) -> '(1 2 3 4)
(define (myAppend lst arr) ; реализация append
  (if (empty? lst)
      arr
      (cons (car lst) (myAppend (cdr lst) arr))))

(define (z2 lst)
  (define (iter lst arr a k)
    (if (empty? lst)
        (if (empty? arr)
            (cons (cons a k) null)                                               ; возвращаем пару (a . k) для последнего элемента, который встретился в списке
            (myAppend (cons (cons a k) null) (iter (cdr arr) null (car arr) 1))) ; возвращаем пару (a . k) для элемента a и список пар от след элементов
        (if (equal? (car lst) a)                                                 ; пробегаемся по списку, сравнивая элементы оставшегося списка с текущим элементом
            (iter (cdr lst) arr a (+ k 1))
            (iter (cdr lst) (myAppend arr (cons (car lst) null)) a k))))
  (if (empty? lst)                                                               ; обработка пустого списка
      null
      (iter (cdr lst) '() (car lst) 1)))

;-------------------------------------------------------------------

(define (is_fibo? x)
  (define (it a b)
    (if (= a x)                ; если число фибоначчи 
         #t
         (if (> a x)           ; пока "нижнее" число меньше x
             #f
             (it b (+ b a))))) ; находим след число
  (it 0 1))                    ; 0 и 1 - первые числа фибоначчи 

(define (z3 lst)
  (define (iter lst arr counter)
    (if (empty? lst)
        counter
        (if (is_fibo? (car lst))
            (if (in (car lst) arr)
                (iter (cdr lst) (cons (car lst) arr) counter)
                (iter (cdr lst) (cons (car lst) arr) (+ counter 1)))
            (iter (cdr lst) arr counter))))
  (iter lst '() 0))

;--------------------------------------------------------------------

(define (gcd_ a b) ; НОД
  (if (= a 0)
      b
      (gcd_ (% b a) a)))

(define (z4 lst arr)
  (if (or (empty? lst) (empty? arr))                                 ; итерация, пока один из списков не пуст
      null
      (if (= (gcd_ (abs (car lst)) (abs (car arr))) 1)               ; взаимно просты, добавляем
          (cons (cons (car lst) (car arr)) (z4 (cdr lst) (cdr arr)))
          (z4 (cdr lst) (cdr arr)))))

;--------------------------------------------------------------------

(define (z5 lst)               
  (define (iter arr a)
    (if (empty? arr)                                       ; база рекурсии
        (cons lst null)                                    ; возвращаем lst
        (myAppend (cons a null)                            ; добавляем a к результату iter от (a + car lst), (cdr lst)
                  (iter (cdr arr)
                        (myAppend a (cons (car arr) null))
  ))))
  (if (empty? lst)                                         ; если начальный список пуст
      null
      (iter (cdr lst) (cons (car lst) null))))

; Накапливаем a, добавляя первый элемент из lst в конец a
; к текущему a присоединяем след a, пока тот не равен lst


























